﻿#region Copyright Information
// // ****************************************************************
// // Feel free to extend or modify the code of the application to your needs. 
// // But remember do it for the Glory of our Lord Jesus Christ
// // ****************************************************************
#endregion
#region Usings

using System;
using System.Collections.Generic;

#endregion

namespace Utils.ServiceLocator
{
	/// <summary>
	/// Implements the functionality of the Service Locator pattern.
	/// </summary>
	public class ServiceLocator
	{
		/// <summary>
		/// Holds all the services.
		/// </summary>
		private readonly IDictionary<Type, object> services = new Dictionary<Type, object>();

        /// <summary>
        /// Private constructor for <see cref="ServiceLocator"/> class.
        /// </summary>
        private ServiceLocator()
        {
            
        }

	    /// <summary>
	    /// Private field for <see cref="ServiceLocator"/> class.
	    /// </summary>
	    private static ServiceLocator field;

        /// <summary>
        /// Singleton instance for <see cref="ServiceLocator"/> class.
        /// </summary>
	    public static ServiceLocator Instance
	    {
	        get { return field ?? (field = new ServiceLocator()); }
	    }

		#region ServiceLocator Methods

		/// <summary>
		/// Register a instance of the specified type.
		/// </summary>
		/// <typeparam name="T">The type of the instace.</typeparam>
		/// <remarks> It will contain only one reference of the specified type.</remarks>
		public void Register<T>(object value)
		{
			if (!services.ContainsKey(typeof(T)))
				services[typeof(T)] = value;
		}

		/// <summary>
		/// Returns the type of the instance register.
		/// </summary>
		/// <typeparam name="T">The type of the instance.</typeparam>
		/// <returns></returns>
		public T Get<T>()
		{
			try
			{
				return (T)services[typeof(T)];
			}
			catch (Exception e)
			{
				throw new Exception(e.Message);
			}
		}

		/// <summary>
		/// Unregister the type specified.
		/// </summary>
		/// <typeparam name="T">The type specified.</typeparam>
		public void Unregister<T>()
		{
			services[typeof(T)] = null;
		}

		#endregion
	}
}